﻿#pragma once
#include <IVtkTools_ShapeDataSource.hxx>
#include <IVtkTools_ShapeObject.hxx>
#include <IVtkTools_ShapePicker.hxx>
#include <vtkInteractorStyleTrackballCamera.h>

#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

#include <vtkRendererCollection.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkProperty.h>

#include <vtkOrientationMarkerWidget.h>
#include <vtkPropPicker.h>
#include <vtkAssemblyPath.h>

// VIS includes
#include <IVtkOCC_Shape.hxx>
#include <IVtkTools_DisplayModeFilter.hxx>
#include <IVtkTools_ShapeDataSource.hxx>
#include <IVtkTools_ShapeObject.hxx>
#include <IVtkTools_ShapePicker.hxx>
#include <IVtkTools_SubPolyDataFilter.hxx>
#include "OccGeoSelector.h"
#include "QIVtkSelectionPipeline.h"
#include <TopoDS_Vertex.hxx>

class QVTKInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:

    static QVTKInteractorStyle* New();
    vtkTypeMacro(QVTKInteractorStyle, vtkInteractorStyleTrackballCamera);

public:

    QVTKInteractorStyle();
    /**
     * @brief Constructor for QVTKInteractorStyle.
     * Initializes a new instance of the QVTKInteractorStyle class.
     */
   /* QVTKInteractorStyle(modelSoft* myModelSoft);*/

    /**
     * @brief Destructor for QVTKInteractorStyle.
     * Cleans up any resources used by the instance.
     */
    ~QVTKInteractorStyle() override;

public:

    void setSelectionMode(IVtk_SelectionMode mode);
    //void OnSelection(Standard_Boolean appendId);
    bool SelectVertex(Standard_Integer theX, Standard_Integer theY);
    void Select(const Standard_Boolean appendId);
    void MoveTo(Standard_Integer theX, Standard_Integer theY);
    void setVTKRenderWindow(vtkRenderWindow* vtkRenderWindow);
    void setRenderer(const vtkSmartPointer<vtkRenderer>& theRenderer);
    void setOcctPicker(const vtkSmartPointer<IVtkTools_ShapePicker>& thePicker);
    void setCurrSelector(OccGeoSelector* selector);
    //void setModelSoft(modelSoft* myModelSoft);
    void clearCurrSelector();
    void clearShapeMaps();
    /**
    * @brief Adds a selection pipeline to the interactor style.
    * @param pipeline A handle to the QIVtkSelectionPipeline.
    * @param id The ID associated with the pipeline.
    */
    void addPipeline(const Handle(QIVtkSelectionPipeline) pipeline, IVtk_IdType id);

    void removePipeline(IVtk_IdType id);

    Standard_Real DistanceIn(const TopoDS_Shape& S1, const TopoDS_Shape& S2);
    Standard_Real DistanceOut(const TopoDS_Shape& S1, const TopoDS_Shape& S2);
    TopoDS_Shape pickNearestEdgePoint(const gp_Pnt& P, const TopoDS_Shape& S);
    //bool pickNearestPoint(const gp_Pnt& P, const gp_Dir& viewDir, const TopoDS_Shape& S, gp_Pnt& relPoint, gp_Dir& faceNormal, bool onlyEdges);
    //TopoDS_Vertex pickNearestEdgePoint(const gp_Pnt& P, const TopoDS_Shape& S);

//Override functions
public:
    /**
     * @brief  Handle the right mouse button press event.
     */
    virtual void OnRightButtonDown() override;

    /**
     * @brief  Handle the left mouse button press event.
     */
    virtual void OnLeftButtonDown() override;

    /**
    * @brief  Handle the left mouse button up event.
    */
    virtual void OnLeftButtonUp() override;

    /**
     * @brief  Method for handling mouse moving event.
     */
    virtual void OnMouseMove() override;

    /**
     * @brief Handles the key press event.
     */
    virtual void OnKeyPress() override;

    /**
     * @brief Handles the key release event.
     */
    virtual void OnKeyRelease() override;

    /**
     * @brief Handles the original left button down event.
     */
    virtual void OnMiddleButtonDown() override;
    /**
     * @brief Handles the Handles the original left button up event.
     */
    virtual void OnMiddleButtonUp() override;




public:
    /*
     *functions to set multiPickers.
     */

    void setOcctPickerEnabled(bool isEnabled) { _occtPickerEnabled = isEnabled; }
    void setCoordPickerEnabled(bool isEnabled) { _coordPickerEnabled = isEnabled; }
    void setPlanePickerEnabled(bool isEnabled) { _planePickerEnabled = isEnabled; }

private:
    vtkActor* LastPickedActor = nullptr;

public:
    std::vector<Handle(QIVtkSelectionPipeline)> actorCollection;
    vtkSmartPointer<vtkProperty> baseProperty = vtkProperty::New();
    vtkSmartPointer<vtkProperty> highlightProperty = vtkProperty::New();

private:
    bool _coordPickerEnabled = false;
    bool _occtPickerEnabled = false;
    bool _planePickerEnabled = false;

public:

    //设置布尔运算标志（是否传输选择Actor）
    void setBrepOperation(bool isEnabled) {
        brepOperation = isEnabled;
    }
    void setTransformOperation(bool isEnabled) {
        transform = isEnabled;
    }

    void setStretchOperation(bool isEnabled) {
        stretchOperation = isEnabled;
    }

    void setRevolOperation(bool isEnabled) {
        revolOperation = isEnabled;
    }

    void setFilletOperation(bool isEnabled) {
        filletOperation = isEnabled;
    }

    void setHollowOperation(bool isEnabled) {
        hollowOperation = isEnabled;
    }

    void setCurveOperation(bool isEnabled) {
        curveOperation = isEnabled;
    }

    void RemoveSelectedActor(Handle(QIVtkSelectionPipeline) delSelPipe);
    
    void SetPipeBaseProperty(Handle(QIVtkSelectionPipeline) pipe) {
        pipe->Actor()->GetProperty()->DeepCopy(baseProperty);
    }

    Standard_Real* getMousePickPos() {
        return mousePickPos;
    }
public:
    // ! Getter and Setters
    [[nodiscard]] vtkSmartPointer<vtkRenderer> getRenderer() const
    {
        return _renderer;
    }

    [[nodiscard]] vtkSmartPointer<IVtkTools_ShapePicker> getOcctPicker() const
    {
        return _occtpicker;
    }

    [[nodiscard]] std::vector<std::reference_wrapper<const TopoDS_Shape>> getSelectedShapes() const
    {
        return _selectedShapes;
    }

    [[nodiscard]] std::vector<Handle(QIVtkSelectionPipeline)> getSelectedPipelines() const
    {
        return _selectPipelines;
    }

    [[nodiscard]] IVtk_SelectionMode getSelectionMode() const
    {
        return _currentSelectionMode;
    }

    [[nodiscard]] OccGeoSelector* getCurrSelector() const
    {
        return m_currSelector;
    }

    [[nodiscard]] NCollection_DataMap<IVtk_IdType, Handle(QIVtkSelectionPipeline)> getShapePipelinesMap() const
    {
        return _shapePipelinesMap;
    }
    //可视化选择点Actor
    vtkSmartPointer<vtkActor> tempSphereActor;
    //选择
    OccGeoSelector* m_currSelector;
private:
    // ! Smart pointer to the shape picker.
    vtkSmartPointer<IVtkTools_ShapePicker> _occtpicker;
    // ! Smart pointer to the VTK renderer.
    vtkSmartPointer<vtkRenderer> _renderer;

    // ! Pointer to the QVTK render window.
    vtkRenderWindow* _qvtkRenderWindow = nullptr;

    int lastPos[2]{ 0, 0 };

    // ! Current selection mode.
    IVtk_SelectionMode _currentSelectionMode = SM_None;

    //存储要渲染的pipelines
    NCollection_DataMap<IVtk_IdType, Handle(QIVtkSelectionPipeline)> _shapePipelinesMap;

    //存储选择的pipeline
    std::vector<Handle(QIVtkSelectionPipeline)> _selectPipelines;

    //Shapes Selected.
    std::vector<std::reference_wrapper<const TopoDS_Shape>> _selectedShapes;

    // ! Map of selected sub-shape IDs.
    NCollection_DataMap<IVtk_IdType, IVtk_ShapeIdList*> _selectedSubShapeIdsMap;

    //存储选择的点
    TopoDS_Shape pickVertex = TopoDS_Shape();
    //! Vertex picked?
    bool vertexPick = false;

    //BrepOperation?
    bool brepOperation = false;

    //transform?
    bool transform = false;

    //stretch?
    bool stretchOperation = false;

    //Revol?
    bool revolOperation = false;
    
    //fillet?
    bool filletOperation = false;

    //hollow?
    bool hollowOperation = false;

    bool curveOperation = false;

    Standard_Real mousePickPos[3];
};
